#include "drv_can.h"
#include "hc32f460_can.h"
#include "delay.h"
#include <stdio.h>
#include "main.h"

static stc_can_rxframe_t stcRxFrame;
static CanConfigData_t configData = {.conf_prsec = 4,.conf_seg1 = 5,.conf_seg2 = 3,.conf_sjw = 3};
static CanTransData_t canData;

CanTransData_t *getCanRecvInfo(void){
	return &canData;
}

static void CAN_RxIrqCallBack(void){
    if(true == CAN_IrqFlgGet(CanRxIrqFlg)){
        CAN_IrqFlgClr(CanRxIrqFlg);
        CAN_Receive(&stcRxFrame);
		if(canData.recv_ok_flag == 0){
			canData.stdId = stcRxFrame.StdID;
			canData.ExtId = stcRxFrame.ExtID;
			canData.dataLen = stcRxFrame.Cst.Control_f.DLC;
			memcpy(canData.data,stcRxFrame.Data,8);
			canData.recv_ok_flag = 1;
		}
		MEM_ZERO_STRUCT(stcRxFrame);
    }
    if(true == CAN_IrqFlgGet(CanTxPrimaryIrqFlg)){
        CAN_IrqFlgClr(CanTxPrimaryIrqFlg);
    }
	volatile uint32_t *u32pIF = NULL;
	u32pIF = (volatile uint32_t*)(&M4_CAN->RTIF);
	*u32pIF = 0xFF;
}

void drv_can_sleep_enter(void){
	stc_port_init_t stcPortInit;
	MEM_ZERO_STRUCT(stcPortInit);
	CAN_DeInit();
	stcPortInit.enPinMode = Pin_Mode_Out;
	stcPortInit.enExInt = Disable;
	stcPortInit.enPullUp = Disable;
	PORT_SetFunc(CAN_RX_PORT, CAN_RX_PIN, Func_Gpio, Disable);
	PORT_SetFunc(CAN_TX_PORT, CAN_TX_PIN, Func_Gpio, Disable);
	PORT_Init(CAN_RX_PORT, CAN_RX_PIN, &stcPortInit);
	PORT_Init(CAN_TX_PORT, CAN_TX_PIN, &stcPortInit);
	PORT_ResetBits(CAN_RX_PORT, CAN_RX_PIN);
	PORT_ResetBits(CAN_TX_PORT, CAN_TX_PIN);	
}

void drv_can_sleep_exit(void){
	drv_can_init(configData.conf_prsec,configData.conf_seg1,configData.conf_seg2,configData.conf_sjw);
}

uint8_t can_send_msg(CanTransData_t *msg){
	stc_can_txframe_t stcTxFrame;
	uint8_t i = 0u;
	uint16_t j=0;
	MEM_ZERO_STRUCT(stcTxFrame);
	if(msg->dataLen>8){
		msg->dataLen=8;
	}
	//<<Can Tx
	stcTxFrame.StdID         = msg->stdId;
	stcTxFrame.ExtID         = msg->ExtId;
	stcTxFrame.Control_f.DLC = msg->dataLen;
	stcTxFrame.Control_f.IDE = 1;
	for(i=0u; i<msg->dataLen; i++){
			stcTxFrame.Data[i] = msg->data[i];
	}
	CAN_SetFrame(&stcTxFrame);
	CAN_TransmitCmd(CanPTBTxCmd);
	return 0;
}

//seg1>=seg2+1  seg2>=sjw  seg1->0-63 seg2->0-7  sjw->0-7
//baud=canclk/prsec/(seg1+seg2)
//canclk=8M
//void MYCAN_Init(4,10,6,6)//125K
//void MYCAN_Init(8,6,4,4)//100K
//void MYCAN_Init(4,6,4,4)//200K
//void MYCAN_Init(4,5,3,3)//250K
//void MYCAN_Init(2,5,3,3)//500K
void drv_can_init(uint8_t prsec,uint8_t seg1,uint8_t seg2,uint8_t sjw){
	configData.conf_prsec = prsec;
	configData.conf_seg1 = seg1;
	configData.conf_seg2 = seg2;
	configData.conf_sjw = sjw;
	
	stc_irq_regi_conf_t     stcIrqRegiConf;
	stc_can_init_config_t stcCanInitCfg;
    stc_can_filter_t astcFilters[CAN_FILTERS_COUNT] = {
        {0x00000000ul, 0x1FFFFFFFul, CanFilterSel1, CanAllFrames}
    };

    PWC_RamOpMdConfig(HighSpeedMd);
    PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
    PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);

    PORT_SetFunc(CAN_RX_PORT, CAN_RX_PIN, Func_Can1_Rx, Disable);
    PORT_SetFunc(CAN_TX_PORT, CAN_TX_PIN, Func_Can1_Tx, Disable);

    MEM_ZERO_STRUCT(stcCanInitCfg);
    stcCanInitCfg.stcCanBt.PRESC = prsec-1u;
    stcCanInitCfg.stcCanBt.SEG_1 = seg1-2u;
    stcCanInitCfg.stcCanBt.SEG_2 = seg2-1u;
    stcCanInitCfg.stcCanBt.SJW   = sjw-1u;
    stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
    stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;
    stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
    stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
    stcCanInitCfg.enCanSAck      = CanSelfAckEnable;
    stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;
    stcCanInitCfg.pstcFilter     = astcFilters;
    stcCanInitCfg.u8FilterCount  = CAN_FILTERS_COUNT;
    CAN_Init(&stcCanInitCfg);
		
	stcIrqRegiConf.enIRQn = Int005_IRQn;
    stcIrqRegiConf.enIntSrc = INT_CAN_INT;
    stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
    enIrqRegistration(&stcIrqRegiConf);
    NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}